package org.tim.io;

import java.util.ArrayList;
import java.lang.Thread;
import java.lang.Runnable;
import java.lang.InterruptedException;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;

/**
 * This class monitors an input stream and notifies his listeners everytime it receives a new line
 * <p>This class is based on a BufferedReader and is usefull for <code>System.in</code>, or input streams received froms <code>Sockets</code></p>
 * @author Tim Fennis
 */
public final class InputStreamMonitor implements Runnable {
	
	private ArrayList<InputStreamListener> listeners = new ArrayList<InputStreamListener>();
	private BufferedReader br = null;
	private Thread me = null;
	
	/**
	 * Create an input stream monitor with a given input stream
	 * @param in The input stream
	 */
	public InputStreamMonitor ( InputStream in ) {
		setStream( in );
		me = new Thread ( this );
		me.start();
	}
		
	public void setStream ( InputStream in ) {
		br = new BufferedReader( new InputStreamReader ( in ) );
		if ( me != null && me.interrupted() ) {
			me = new Thread( this );
			me.start();
		}
	}
	
	public void addListener ( InputStreamListener l ) {
		listeners.add( l );
	}
	
	/**
     *
	 */
	public void removeListener ( InputStreamListener l ) {
		listeners.remove( listeners.indexOf(l) );
	}
	
	/**
	 *
	 */
	public void run ( ) {
		String buf = null;
		
		try {
			while ( true && ! me.isInterrupted() ) {
			
				if ( (buf = br.readLine()) == null ) {
					break;
				}
				
				if ( ! listeners.isEmpty() ) {
					for ( int i = 0 ; i < listeners.size() ; i++ ) {
						listeners.get(i).messageReceived(buf);
					}
				}
				
			}
		} catch ( IOException io ) {
			
		} finally {
			if ( ! listeners.isEmpty() ) {
				for ( int i = 0 ; i < listeners.size() ; i++ ) {
					listeners.get(i).messageReceived(null);
				}
			}
		}
	}

}